#pragma once

#include "ecal/ecal.h"
#include "ecal/msg/protobuf/publisher.h"
#include "ecal/msg/protobuf/subscriber.h"
#include "xict_common/perception/detection/yolov5trt_det.h"
#include "xict_cpp/core/stage/base.h"
#include "xict_cpp/core/stage/draw_trajectory_processor.h"
#include "xict_driver/utils/data_converter.h"
#include "xict_proto/sensor/image.pb.h"

namespace xict_cpp {
    namespace core {
        namespace stage {

            struct StreamProcessorStageParams {
                /// @brief 前视图像的topic名
                std::string front_image_topic = "front_image";
                /// @brief 后视图像的topic名
                std::string back_image_topic = "back_image";
                /// @brief 左视图像的topic名
                std::string left_image_topic = "left_image";
                /// @brief 右视图像的topic名
                std::string right_image_topic = "right_image";

                /// @brief 前视图像检测后发布的topic名
                std::string yolo_front = "yolo_front";
                /// @brief 后视图像检测后发布的topic名
                std::string yolo_back = "yolo_back";
                /// @brief 左视图像检测后发布的topic名
                std::string yolo_left = "yolo_left";
                /// @brief 右视图像检测后发布的topic名
                std::string yolo_right = "yolo_right";

                /// @brief rtsp推流使能开关
                bool rtsp_enable = false;
                /// @brief rtsp基础码流
                std::string rtsp_url = "rtsp://127.0.0.1:8554/";
                /// @brief rtsp推流比特率
                int rtsp_bitrate = 600;
                /// @brief rtsp推流图像宽度
                int rtsp_width = 640;
                /// @brief rtsp推流图像高度
                int rtsp_height = 480;
                /// @brief rtsp推流帧率
                int rtsp_fps = 30;
                /// @brief rtsp服务端可执行文件
                std::string rtsp_server_exe = "";
                /// @brief rtsp服务端配置文件
                std::string rtsp_server_config = "";

                /// @brief 是否使用模型进行检测
                bool model_flag = false;
                /// @brief TensorRT模型路径
                std::string model_path = "";
                /// @brief 是否有忽略区域
                bool ignore_region_flag = false;
                /// @brief 忽略区域
                std::map<std::string, std::vector<std::vector<cv::Point>>>
                    camera_ignore_regions;
                /// @brief 使用map存储不同相机的mask
                std::map<std::string, cv::Mat> camera_masks;
                /// @brief 图像宽度
                int image_width = 1920;
                /// @brief 图像高度
                int image_height = 1080;
                /// @brief mask图像显示开关
                bool mask_show_flag = false;
            };

            struct StreamProcessorStageSubscriber {
                /// @brief 图像订阅者
                std::shared_ptr<
                    eCAL::protobuf::CSubscriber<xcmg_proto::OpencvImage>>
                    subscriber_front_image;
                std::shared_ptr<
                    eCAL::protobuf::CSubscriber<xcmg_proto::OpencvImage>>
                    subscriber_back_image;
                std::shared_ptr<
                    eCAL::protobuf::CSubscriber<xcmg_proto::OpencvImage>>
                    subscriber_left_image;
                std::shared_ptr<
                    eCAL::protobuf::CSubscriber<xcmg_proto::OpencvImage>>
                    subscriber_right_image;
            };

            struct StreamProcessorStagePublisher {
                /// @brief 检测结果发布者
                std::shared_ptr<
                    eCAL::protobuf::CPublisher<xcmg_proto::OpencvImage>>
                    publisher_yolo_front;
                std::shared_ptr<
                    eCAL::protobuf::CPublisher<xcmg_proto::OpencvImage>>
                    publisher_yolo_back;
                std::shared_ptr<
                    eCAL::protobuf::CPublisher<xcmg_proto::OpencvImage>>
                    publisher_yolo_left;
                std::shared_ptr<
                    eCAL::protobuf::CPublisher<xcmg_proto::OpencvImage>>
                    publisher_yolo_right;
            };

            struct RtspStreamProcessorStagePublisher {
                /// @brief rtsp推流结果发布者
                cv::VideoWriter writer_front;
                cv::VideoWriter writer_back;
                cv::VideoWriter writer_left;
                cv::VideoWriter writer_right;

                std::string rtsp_url_front = "";
                std::string rtsp_url_back  = "";
                std::string rtsp_url_left  = "";
                std::string rtsp_url_right = "";
            };

            class StreamProcessorStage : public Stage {
            public:
                /// @brief 默认构造函数
                StreamProcessorStage() = default;
                /// @brief 默认析构函数
                ~StreamProcessorStage() override = default;

                /// @brief 初始化函数
                bool Init() override;
                /// @brief 初始化函数
                bool Init(const StreamProcessorStageParams& params);
                /// @brief 运行函数
                bool Process() override;
                /// @brief 返回类的名称
                std::string Name() const override;

            protected:
                /// @brief 初始化函数，并返回结果
                bool Initialize() override;
                void Reset() override;

            protected:
                void CallbackImageDetect(
                    const char* topic_name_,
                    const xcmg_proto::OpencvImage& data, long long time_,
                    long long clock_, long long id,
                    std::shared_ptr<
                        eCAL::protobuf::CPublisher<xcmg_proto::OpencvImage>>
                        pub);
                void PushRtsp(std::string topic_name, cv::Mat img);

            private:
                StreamProcessorStageParams params_;

                /// @brief 数据转换器
                std::shared_ptr<xict_driver::utils::DataConverter>
                    data_converter_;
                /// @brief 图像订阅器
                StreamProcessorStageSubscriber image_subscriber_;
                /// @brief 图像检测结果发布器
                StreamProcessorStagePublisher detector_image_publisher_;
                /// @brief 图像检测器
                std::shared_ptr<
                    xict_common::perception::detection::Yolov5TrtDet>
                    detector_ptr_;
                /// @brief rtsp推流发布器
                RtspStreamProcessorStagePublisher rtsp_publisher_;
                /// @brief 线程锁
                std::mutex mt_;
                /// @brief 轨迹线绘制器
                std::shared_ptr<DrawTrajectoryStage> trajectory_processor_;
            };
        }   // namespace stage
    }       // namespace core
}   // namespace xict_cpp
